package com.lz.springboot.mongo.dao;

import java.util.List;
import java.util.Map;

import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Repository;

import com.lz.springboot.mongo.utils.ReflectionUtils;

@Repository
public class BaseMongoDao<T> implements BaseMongoDaoI<T> {

	public MongoTemplate mongoTemplate;

	public BaseMongoDao() {

	}

	@Override
	public T findOne(Map<String, Object> queryParams) {
		Query query = new Query();
		if ((queryParams != null) && (!(queryParams.isEmpty()))) {
			for (String key : queryParams.keySet()) {
				query.addCriteria(new Criteria(key).is(queryParams.get(key)));
			}
		}
		return (T) mongoTemplate.findOne(query, this.getEntityClass());
	}

	@Override
	public List<T> findList(int skip, int limit) {
		Query query = new Query();
		query.with(new Sort(new Order(Direction.ASC, "_id")));
		query.skip(skip).limit(limit);
		return (List<T>) this.mongoTemplate.find(query, this.getEntityClass());
	}

	@Override
	public List<T> findList(Map<String, Object> queryParams) {
		Query query = new Query();
		if ((queryParams != null) && (!(queryParams.isEmpty()))) {
			for (String key : queryParams.keySet()) {
				query.addCriteria(new Criteria(key).is(queryParams.get(key)));
			}
		}
		return (List<T>) this.mongoTemplate.find(query, this.getEntityClass());
	}

	@Override
	public List<T> findList(Map<String, Object> queryParams, int skip, int rows) {
		Query query = new Query();
		if ((queryParams != null) && (!(queryParams.isEmpty()))) {
			for (String key : queryParams.keySet()) {
				query.addCriteria(new Criteria(key).is(queryParams.get(key)));
			}
		}
		query.skip(skip).limit(rows);
		return (List<T>) this.mongoTemplate.find(query, this.getEntityClass());
	}

	@Override
	public long count(Map<String, Object> queryParams) {
		Query query = new Query();
		if ((queryParams != null) && (!(queryParams.isEmpty()))) {
			for (String key : queryParams.keySet()) {
				query.addCriteria(new Criteria(key).is(queryParams.get(key)));
			}
		}
		return mongoTemplate.count(query, this.getEntityClass());
	}

	@Override
	public void insert(T t) {
		this.mongoTemplate.insert(t);
	}

	@Override
	public int update(String id, Map<String, Object> updateParams) {
		Query query = new Query();
		query.addCriteria(new Criteria("_id").is(id));
		Update update = new Update();
		if ((updateParams != null) && (!(updateParams.isEmpty()))) {
			for (String key : updateParams.keySet()) {
				update.set(key, updateParams.get(key));
			}
		}
		return this.mongoTemplate.updateFirst(query, update, this.getEntityClass()).getN();
	}

	@Override
	public int update(Map<String, Object> queryParams, Map<String, Object> updateParams) {
		Query query = new Query();
		if ((queryParams != null) && (!(queryParams.isEmpty()))) {
			for (String key : queryParams.keySet()) {
				query.addCriteria(new Criteria(key).is(queryParams.get(key)));
			}
		}
		Update update = new Update();
		if ((updateParams != null) && (!(updateParams.isEmpty()))) {
			for (String key : updateParams.keySet()) {
				update.set(key, updateParams.get(key));
			}
		}
		return this.mongoTemplate.updateFirst(query, update, this.getEntityClass()).getN();
	}
	
	@Override
	public int upsert(Map<String, Object> queryParams, Map<String, Object> updateParams) {
		Query query = new Query();
		if ((queryParams != null) && (!(queryParams.isEmpty()))) {
			for (String key : queryParams.keySet()) {
				query.addCriteria(new Criteria(key).is(queryParams.get(key)));
			}
		}
		Update update = new Update();
		if ((updateParams != null) && (!(updateParams.isEmpty()))) {
			for (String key : updateParams.keySet()) {
				update.set(key, updateParams.get(key));
			}
		}
		return this.mongoTemplate.upsert(query, update, this.getEntityClass()).getN();
	}

	@Override
	public int deleteById(String id) {
		return mongoTemplate.remove(new Query(Criteria.where("_id").is(id)), this.getEntityClass()).getN();
	}

	/**
	 * 获取需要操作的实体类class
	 * @return
	 */
	private Class<T> getEntityClass() {
		return ReflectionUtils.getSuperClassGenricType(getClass());
	}

}